﻿#include "MyOpenGL.h"
#include <QOpenGLShaderProgram>

#define SHADER(x) #x

MyOpenGL::MyOpenGL(QWidget *parent)
    : QOpenGLWidget(parent)
{

}

MyOpenGL::~MyOpenGL()
{

}

void MyOpenGL::initializeGL()
{
    initializeOpenGLFunctions();

    QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);
    const char *vsrc = SHADER(
        in vec4 vPosition;
        // 输入变量
        in vec4 vColor;
        // 输出变量
        out vec4 color;
        void main() {
            color = vColor;
            gl_Position = vPosition;
        }
    );
    vshader->compileSourceCode(vsrc);

    QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
    const char *fsrc = SHADER(
        // 用来和顶点着色器的输出变量color对应
        in vec4 color;
        // 将color输入的颜色数据输出到着色器管线中用来为图形着色
        out vec4 fColor;
        void main() {
            fColor = color;
        }
    );
    fshader->compileSourceCode(fsrc);

    program = new QOpenGLShaderProgram;
    program->addShader(vshader);
    program->addShader(fshader);

    program->link();
    program->bind();

}

void MyOpenGL::paintGL()
{
    int w = width();
    int h = height();
    int side = qMin(w, h);
    glViewport((w - side)/2, (h - side)/2, side, side);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 顶点位置
    GLfloat vertices[] = {
        -0.8f, 0.8f,
        -0.8f, -0.8f,
        0.8f, -0.8f,
        0.8f, 0.8f
    };

    vbo.create();
    vbo.bind();
    // 为了不覆盖已有数据，对缓存进行扩容
    // 顶点数组有8个元素， 颜色数组有12个元素
    vbo.allocate(vertices, 20*sizeof(GLfloat));

    GLuint vPosition = program->attributeLocation("vPosition");
    program->setAttributeBuffer(vPosition, GL_FLOAT, 0, 2, 0);
    glEnableVertexAttribArray(vPosition);

    // 顶点颜色
    GLfloat colors[] = {
        1.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 1.0f
    };

    // 该函数会替换掉缓存中已有的内容
    /*
     * write(int offset, const void *data, int count)
     * offset: 替换数据开始位置的偏移值。
    */
    vbo.write(8*sizeof(GLfloat), colors, 12*sizeof(GLfloat));
    GLuint vColor = program->attributeLocation("vColor");
    program->setAttributeBuffer(vColor, GL_FLOAT, 8*sizeof(GLfloat), 3, 0);
    glEnableVertexAttribArray(vColor);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}

void MyOpenGL::resizeGL(int w, int h)
{

}
